/*****************************************************************************
  Exception handlers and startup code for a generic ARM target.

  Copyright (c) 2014 Rowley Associates Limited.

  This file may be distributed under the terms of the License Agreement
  provided with this software.

  THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *****************************************************************************/

/*****************************************************************************
 *                           Preprocessor Definitions
 *                           ------------------------
 *
 * STARTUP_FROM_RESET
 *
 *   If defined, the program will startup from power-on/reset. If not defined
 *   the program will just loop endlessly from power-on/reset.
 *
 *   This definition is not defined by default on this target because the
 *   debugger is unable to reset this target and maintain control of it over the
 *   JTAG interface. The advantage of doing this is that it allows the debugger
 *   to reset the CPU and run programs from a known reset CPU state on each run.
 *   It also acts as a safety net if you accidently download a program in FLASH
 *   that crashes and prevents the debugger from taking control over JTAG
 *   rendering the target unusable over JTAG. The obvious disadvantage of doing
 *   this is that your application will not startup without the debugger.
 *
 *   We advise that on this target you keep STARTUP_FROM_RESET undefined whilst
 *   you are developing and only define STARTUP_FROM_RESET when development is
 *   complete.
 *
 *****************************************************************************/

#ifndef APP_ENTRY_POINT
#define APP_ENTRY_POINT main
#endif

  .extern APP_ENTRY_POINT

  .section .vectors, "ax"
  .code 32
  .align 0
  .global _vectors
  .global reset_handler
  
_vectors:
#ifdef STARTUP_FROM_RESET
  ldr pc, =reset_handler
#else
  b .                                           /* reset - infinite loop */
#endif
  ldr pc, =undef_handler
  ldr pc, =swi_handler
  ldr pc, =pabort_handler
  ldr pc, =dabort_handler
  nop
  ldr pc, =irq_handler
  ldr pc, =fiq_handler

  .section .init, "ax"
  .code 32
  .align 0
reset_handler:
  //
  // Simplified startup
  // Flashloaders do not have a segment init etc.
  // The only thing we need to make sure is that we setup the stackpointer for the debug build, to make debugging from main() working
  //
  mrs r0, cpsr
  bic r0, r0, #0x1F
  orr r1, r0, #0x1F /* System mode */
  msr cpsr_cxsf, r1
  ldr sp, =__stack_end__
  mov r0, #0
  mov r1, #0
  ldr r2, =APP_ENTRY_POINT
  mov lr, pc
  bx r2
  //
  // Only one handler for all exceptions
  //
  .global pabort_handler
  .type pabort_handler, function
pabort_handler:
  .global dabort_handler
  .type dabort_handler, function
dabort_handler:
  .global swi_handler
  .type swi_handler, function
swi_handler:
  .global irq_handler
  .type irq_handler, function
irq_handler:
  .global fiq_handler
  .type fiq_handler, function
fiq_handler:
  .global undef_handler
  .type undef_handler, function
undef_handler:
  b undef_handler
  //
  // Setup attibutes of stack and heap sections
  // so they don't take up unnecessary room in the elf file
  //
  .section .stack, "wa", %nobits
  .section .stack_abt, "wa", %nobits
  .section .stack_irq, "wa", %nobits
  .section .stack_fiq, "wa", %nobits
  .section .stack_svc, "wa", %nobits
  .section .stack_und, "wa", %nobits
  .section .heap, "wa", %nobits

